Varför producerar vissa slumpmässiga strängar färger när de matas in som bakgrundsfärger i HTML? Till exempel: test ... producerar ett dokument med röd bakgrund i alla webbläsare och plattformar. Intressant, medan chucknorri producerar en röd bakgrund också, producerar chucknorr en gul bakgrund. Vad händer här?
2020-12-07 21:56:59
Det är en hållning från Netscape-dagarna: Saknade siffror behandlas som 0 [...]. En felaktig siffra tolkas helt enkelt som 0. Till exempel är värdena # F0F0F0, F0F0F0, F0F0F, #FxFxFx och FxFxFx samma. Det är från blogginlägget Lite rant om Microsoft Internet Explorer färgparsning som täcker det i detalj, inklusive olika längder av färgvärden etc. Om vi tillämpar reglerna i tur och ordning från blogginlägget får vi följande: Byt ut alla ogiltiga hexadecimala tecken med 0: chucknorris blir c00c0000000 Bläddra till nästa totala antal tecken som kan delas med 3 (11 → 12): c00c 0000 0000 Dela upp i tre lika stora grupper, där varje komponent representerar motsvarande färgkomponent i en RGB-färg: RGB (c00c, 0000, 0000) Avkorta vart och ett av argumenten från höger ner till två tecken. Som slutligen ger följande resultat: RGB (c0, 00, 00) = # C00000 eller RGB (192, 0, 0) Här är ett exempel som visar attributet bgcolor i aktion, för att producera denna "fantastiska" färgprov:chuck norris Herr T ninjaturtle Detta svarar också på den andra delen av frågan: Varför producerar bgcolor = "chucknorr" en gul färg? Om vi tillämpar reglerna är strängen: c00c00000 => c00 c00 000 => c0 c0 00 [RGB (192, 192, 0)] Vilket ger en ljusgul guldfärg. Eftersom strängen börjar med nio tecken behåller vi den andra ”C” den här gången, varför den hamnar i det slutliga färgvärdet. Jag stötte ursprungligen på detta när någon påpekade att du kunde göra color = "crap" och, ja, det blir brunt. | Jag är ledsen att inte hålla med, men enligt reglerna för att analysera ett äldre färgvärde från @Yuhong Bao, motsvarar chucknorris INTE # CC0000, utan snarare # C00000, en mycket liknande men lite annorlunda nyans av rött. Jag använde Firefox ColorZilla-tillägget för att verifiera detta. Reglerna säger: gör strängen till en längd som är en multipel av 3 genom att lägga till 0: chucknorris0 separera strängen i tre lika långa strängar: chuc knor ris0 trunka varje sträng till två tecken: ch kn ri behåll hex-värdena och lägg till 0 om det behövs: C0 00 00 Jag kunde använda dessa regler för att korrekt tolka följande strängar: LuckyCharms Tur LuckBeALady LuckBeALadyTonight GangnamStyle UPPDATERING: De ursprungliga svararna som sa att färgen var # CC0000 har sedan redigerat sina svar för att inkludera rättelsen. | De flesta webbläsare ignorerar helt enkelt NON-hex-värden i din färgsträng och ersätter icke-hexadecimiska siffror med nollor. ChuCknorris översätts till c00c0000000. Vid denna punkt delar webbläsaren strängen i tre lika delar, vilket indikerar röda, gröna och blå värden: c00c 0000 0000. Extra bitar i varje sektion ignoreras, vilket gör det slutliga resultatet # c00000 som är en rödaktig färg. Observera att detta inte gäller CSS-färgparsning, som följer CSS-standarden. sjuk crap gräs Rödaktig
Samma som ovan
Svart
| Anledningen är att webbläsaren inte kan förstå den och försöka på något sätt översätta den till vad den kan förstå och i detta fall till ett hexadecimalt värde! ... chucknorris börjar med c vilket är igenkänt tecken i hexadecimal, det konverterar också alla okända tecken till 0! Så chucknorris i hexadecimalt format blir: c00c00000000, alla andra tecken blir 0 och c förblir där de är ... Nu delas de med 3 för RGB (röd, grön, blå) ... R: c00c, G: 0000, B: 0000 ... Men vi vet att giltigt hexadecimalt för RGB bara är två tecken, betyder R: c0, G: 00, B: 00 Så det verkliga resultatet är: bgcolor = "# c00000"; Jag har också lagt till stegen i bilden som en snabb referens för dig: | Webbläsaren försöker konvertera chucknorris till hex-färgkod eftersom det inte är ett giltigt värde. I chucknorris är allt utom c inte ett giltigt hex-värde. Så det omvandlas till c00c00000000. Som blir # c00000, en nyans av rött. Detta verkar vara ett problem främst med Internet Explorer och Opera (12) eftersom både Chrome (31) och Firefox (26) bara ignorerar detta. P.S. Siffrorna inom parentes är de webbläsarversioner jag testade på. På en lättare ton Chuck Norris överensstämmer inte med webbstandarder. Webbstandarder överensstämmer till honom. # BADA55 | WHATWG HTML-specifikationen har den exakta algoritmen för att analysera en äldre färgvärde: https://html.spec.whatwg.org/multipage/infrastructure.html#rules-for-parsing-a-legacy-colour-value. Koden Netscape Classic som används för att analysera färgsträngar är öppen källkod: https://dxr.mozilla.org/classic/source/lib/layout/layimage.c#155. Lägg till exempel märke till att varje tecken tolkas som en hexadecimisk siffra och sedan flyttas till ett 32-bitars heltal utan att kontrollera om det finns överflöd. Endast åtta hex-siffror passar in i ett 32-bitars heltal, vilket är anledningen till att endast de sista åtta tecknen beaktas. Efter att ha analyserat hex-siffrorna i 32-bitars heltal trunkeras de sedan i 8-bitars heltal genom att dela dem med 16 tills de passar in i 8-bitar, varför ledande nollor ignoreras. Uppdatering: Den här koden matchar inte exakt vad som definieras i specifikationen, men den enda skillnaden är att det finns några kodrader. Jag tror att det är dessa rader som har lagts till (i Netscape 4): om (bytes_per_val> 4) { bytes_per_val = 4; } | Svar: Webbläsaren försöker konvertera chucknorris till ett hexadecimalt värde. Eftersom c är det enda giltiga hex-tecknet i chucknorris blir värdet till: c00c00000000 (0 för alla ogiltiga värden). Webbläsaren delar sedan upp resultatet i 3 grupp: Röd = c00c, Grön = 0000, Blå = 0000. Eftersom giltiga hex-värden för html-bakgrunder endast innehåller två siffror för varje färgtyp (r, g, b), trunkeras de två sista siffrorna från varje grupp, vilket ger ett rgb-värde på c00000 vilket är en tegelröd-tonad färg. | chucknorris börjar med c, och webbläsaren läser det i ett hexadecimalt värde. Eftersom A, B, C, D, E och F är tecken i hexadecimal. Webbläsaren konverterar chucknorris till ett hexadecimalt värde, C00C00000000. Sedan konverteras hexadecimalt C00C00000000 till RGB-format (dividerat med 3): C00C00000000 ⇒ R: C00C, G: 0000, B: 0000 Webbläsaren behöver bara två siffror för att ange färgen: R: C00C, G: 0000, B: 0000 ⇒ R: C0, G: 00, B: 00 ⇒ C00000 Slutligen, visa bgcolor = C00000 i webbläsaren. Här är ett exempel som visar det:| Reglerna för att analysera färger på äldre attribut innebär ytterligare steg än de som nämns i befintliga svar. Den trunkerade komponenten till två siffror beskrivs som: Kasta alla tecken utom de sista åtta Kasta ledande nollor en efter en så länge som alla komponenter har en ledande noll Kasta alla tecken utom de första 2 Några exempel: oooFoooFoooF 000F 000F 000F <- byt ut, kuddar och bitar 0F 0F 0F <- ledande nollar trunkerade 0F 0F 0F <- trunkeras till 2 tecken från höger oooFooFFoFFF 000F 00FF 0FFF <- byt ut, kuddar och bitar 00F 0FF FFF <- ledande nollar trunkeras 00 0F FF <- trunkeras till 2 tecken från höger ABCooooooABCooooooABCoooooo ABC000000 ABC000000 ABC000000 <- byt ut, pad och bit BC000000 BC000000 BC000000 <- trunkeras till 8 tecken från vänster BC BC BC <- trunkeras till 2 tecken från höger AoCooooooAoCooooooAoCoooooo A0C000000 A0C000000 A0C000000 <- byt ut, pad och bit 0C000000 0C000000 0C000000 <- trunkeras till 8 tecken från vänster C000000 C000000 C000000 <- ledande nollor trunkerade C0 C0 C0 <- trunkeras till 2 tecken från höger Nedan följer en delvis implementering av algoritmen. Det hanterar inte fel eller fall där användaren anger en giltig färg. funktion parseColor (input) { // todo: returnera fel om inmatningen är "" input = input.trim (); // todo: returnera fel om inmatningen är "transparent" // todo: returnera motsvarande #rrggbb om input är en namngiven färg // todo: return #rrggbb if input matches #rgb // todo: ersätt unicode-kodpunkter som är större än U + FFFF med 00 if (input.length> 128) { input = input.slice (0, 128); } if (input.charAt (0) === "#") { input = input.slice (1); } input = input.replace (/ [^ 0-9A-Fa-f] / g, "0"); medan (input.length === 0 || input.length% 3> 0) { input + = "0"; } var r = input.slice (0, input.length / 3); var g = input.slice (input.length / 3, input.length * 2/3); var b = input.slice (input.length * 2/3); om (rlängd> 8) { r = r.skiva (-8); g = g.skiva (-8); b = b.skiva (-8); } medan (r.length> 2 && r.charAt (0) === "0" && g.charAt (0) === "0" && b.charAt (0) === "0") { r = r.skiva (1); g = g. skiva (1); b = b.skiva (1); } om (r.längd> 2) { r = r.skiva (0, 2); g = g.skiva (0, 2); b = b.skiva (0, 2); } returnera "#" + r.padStart (2, "0") + g.padStart (2, "0") + b.padStart (2, "0"); } $ (funktion () { $ ("# input"). on ("ändra", funktion () { var input = $ (detta) .val (); var color = parseColor (input); var $ celler = $ ("# resultat tbody td"); $ cells.eq (0) .attr ("bgcolor", input); $ cells.eq (1) .attr ("bgcolor", färg); varvärde: https://html.spec.whatwg.org/multipage/infrastructure.html#rules-for-parsing-a-legacy-colour-value. Koden Netscape Classic som används för att analysera färgsträngar är öppen källkod: https://dxr.mozilla.org/classic/source/lib/layout/layimage.c#155. Lägg till exempel märke till att varje tecken tolkas som en hexadecimisk siffra och sedan flyttas till ett 32-bitars heltal utan att kontrollera om det finns överflöd. Endast åtta hex-siffror passar in i ett 32-bitars heltal, vilket är anledningen till att endast de sista åtta tecknen beaktas. Efter att ha analyserat hex-siffrorna i 32-bitars heltal trunkeras de sedan i 8-bitars heltal genom att dela dem med 16 tills de passar in i 8-bitar, varför ledande nollor ignoreras. Uppdatering: Den här koden matchar inte exakt vad som definieras i specifikationen, men den enda skillnaden är att det finns några kodrader. Jag tror att det är dessa rader som har lagts till (i Netscape 4): om (bytes_per_val> 4) { bytes_per_val = 4; } | Svar: Webbläsaren försöker konvertera chucknorris till ett hexadecimalt värde. Eftersom c är det enda giltiga hex-tecknet i chucknorris blir värdet till: c00c00000000 (0 för alla ogiltiga värden). Webbläsaren delar sedan upp resultatet i 3 grupp: Röd = c00c, Grön = 0000, Blå = 0000. Eftersom giltiga hex-värden för html-bakgrunder endast innehåller två siffror för varje färgtyp (r, g, b), trunkeras de två sista siffrorna från varje grupp, vilket ger ett rgb-värde på c00000 vilket är en tegelröd-tonad färg. | chucknorris börjar med c, och webbläsaren läser det i ett hexadecimalt värde. Eftersom A, B, C, D, E och F är tecken i hexadecimal. Webbläsaren konverterar chucknorris till ett hexadecimalt värde, C00C00000000. Sedan konverteras hexadecimalt C00C00000000 till RGB-format (dividerat med 3): C00C00000000 ⇒ R: C00C, G: 0000, B: 0000 Webbläsaren behöver bara två siffror för att ange färgen: R: C00C, G: 0000, B: 0000 ⇒ R: C0, G: 00, B: 00 ⇒ C00000 Slutligen, visa bgcolor = C00000 i webbläsaren. Här är ett exempel som visar det: chucknorris c00c00000000 c00000 | Reglerna för att analysera färger på äldre attribut innebär ytterligare steg än de som nämns i befintliga svar. Den trunkerade komponenten till två siffror beskrivs som: Kasta alla tecken utom de sista åtta Kasta ledande nollor en efter en så länge som alla komponenter har en ledande noll Kasta alla tecken utom de första 2 Några exempel: oooFoooFoooF 000F 000F 000F <- byt ut, kuddar och bitar 0F 0F 0F <- ledande nollar trunkerade 0F 0F 0F <- trunkeras till 2 tecken från höger oooFooFFoFFF 000F 00FF 0FFF <- byt ut, kuddar och bitar 00F 0FF FFF <- ledande nollar trunkeras 00 0F FF <- trunkeras till 2 tecken från höger ABCooooooABCooooooABCoooooo ABC000000 ABC000000 ABC000000 <- byt ut, pad och bit BC000000 BC000000 BC000000 <- trunkeras till 8 tecken från vänster BC BC BC <- trunkeras till 2 tecken från höger AoCooooooAoCooooooAoCoooooo A0C000000 A0C000000 A0C000000 <- byt ut, pad och bit 0C000000 0C000000 0C000000 <- trunkeras till 8 tecken från vänster C000000 C000000 C000000 <- ledande nollor trunkerade C0 C0 C0 <- trunkeras till 2 tecken från höger Nedan följer en delvis implementering av algoritmen. Det hanterar inte fel eller fall där användaren anger en giltig färg. funktion parseColor (input) { // todo: returnera fel om inmatningen är "" input = input.trim (); // todo: returnera fel om inmatningen är "transparent" // todo: returnera motsvarande #rrggbb om input är en namngiven färg // todo: return #rrggbb if input matches #rgb // todo: ersätt unicode-kodpunkter som är större än U + FFFF med 00 if (input.length> 128) { input = input.slice (0, 128); } if (input.charAt (0) === "#") { input = input.slice (1); } input = input.replace (/ [^ 0-9A-Fa-f] / g, "0"); medan (input.length === 0 || input.length% 3> 0) { input + = "0"; } var r = input.slice (0, input.length / 3); var g = input.slice (input.length / 3, input.length * 2/3); var b = input.slice (input.length * 2/3); om (rlängd> 8) { r = r.skiva (-8); g = g.skiva (-8); b = b.skiva (-8); } medan (r.length> 2 && r.charAt (0) === "0" && g.charAt (0) === "0" && b.charAt (0) === "0") { r = r.skiva (1); g = g. skiva (1); b = b.skiva (1); } om (r.längd> 2) { r = r.skiva (0, 2); g = g.skiva (0, 2); b = b.skiva (0, 2); } returnera "#" + r.padStart (2, "0") + g.padStart (2, "0") + b.padStart (2, "0"); } $ (funktion () { $ ("# input"). on ("ändra", funktion () { var input = $ (detta) .val (); var color = parseColor (input); var $ celler = $ ("# resultat tbody td"); $ cells.eq (0) .attr ("bgcolor", input); $ cells.eq (1) .attr ("bgcolor", färg); var chucknorris c00c00000000 c00000